package com.xxl.job.core.rpc.netcom;

import java.util.HashMap;
import java.util.Map;

import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;

import org.springframework.cglib.reflect.FastClass;
import org.springframework.cglib.reflect.FastMethod;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.ibm.risk.common.rest.RestService;
import com.xxl.job.core.biz.model.ReturnT;
import com.xxl.job.core.registry.RegistHelper;
import com.xxl.job.core.rpc.codec.RpcRequest;
import com.xxl.job.core.rpc.codec.RpcResponse;
import com.xxl.job.core.thread.ExecutorRegistryThread;

/**
 * netcom init
 * @author xuxueli 2015-10-31 22:54:27
 */
@RestService
@Path("/jobs")
@Produces(MediaType.APPLICATION_JSON)
public class NetComServerFactory  {
	// private static final Logger logger = LoggerFactory.getLogger(NetComServerFactory.class);

	// ---------------------- server start ----------------------
	// JettyServer server = new JettyServer();
	public void start(String address, String appName, RegistHelper registHelper) throws Exception {
		// server.start(port, ip, appName, registHelper);
		ExecutorRegistryThread.getInstance().start(address, appName, registHelper);
	}

	// ---------------------- server destroy ----------------------
	public void destroy(){
		ExecutorRegistryThread.getInstance().toStop();
	}

	// ---------------------- server init ----------------------
	/**
	 * init local rpc service map
	 */
	private static Map<String, Object> serviceMap = new HashMap<String, Object>();
	public static void putService(Class<?> iface, Object serviceBean){
		serviceMap.put(iface.getName(), serviceBean);
	}

	@POST
	@Path("/tigger")
	public RpcResponse<Object> invokeService(RpcRequest request) {
		Object serviceBean = serviceMap.get(request.getClassName());

		RpcResponse<Object> response = new RpcResponse<>();

		if (System.currentTimeMillis() - request.getCreateMillisTime() > 60000) {
			response.setResult(new ReturnT<String>(ReturnT.FAIL_CODE, "Timestamp Timeout."));
			return response;
		}

		try {
			Class<?> serviceClass = serviceBean.getClass();
			String methodName = request.getMethodName();
			Class<?>[] parameterTypes = request.getParameterTypes();
			Object[] parameters = request.getParameters();

			FastClass serviceFastClass = FastClass.create(serviceClass);
			FastMethod serviceFastMethod = serviceFastClass.getMethod(methodName, parameterTypes);
			for (int i = 0; i < parameterTypes.length; i++) {
				Class<?> pClz = parameterTypes[i];
				if (!pClz.isInstance(parameters[i])) {
					// Object param = pClz.newInstance();
					// BeanUtils.copyProperties(param, parameters[i]);
					ObjectMapper om = new ObjectMapper();
					String json = om.writeValueAsString(parameters[i]);
					Object param = om.readValue(json, pClz);

					parameters[i] = param;
				}
			}
			Object result = serviceFastMethod.invoke(serviceBean, parameters);

			response.setResult(result);
		} catch (Throwable t) {
			t.printStackTrace();
			response.setError(t.getMessage());
		}

		return response;
	}

}
